#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <unistd.h>
#include <stddef.h>
#include <stdlib.h>
#include "worker.h"

static long num_processors = 0;
static long context[32] = {0};

void thread_func(void *arg)
{
    int ret;
    size_t cpusize;
    long *cpuid = (long *)arg;
    pthread_t tid = 0;
    cpu_set_t cpuset;

    tid = pthread_self();
    cpusize = sizeof(cpu_set_t);
    CPU_ZERO(&cpuset);
    CPU_SET(*cpuid, &cpuset);
    ret = sched_setaffinity(0, cpusize, &cpuset);
    if (ret == -1) {
        fprintf(stdout, "sched_setaffinity %lu %ld\n", tid, *cpuid);
        return;
    }
    CPU_ZERO(&cpuset);
    ret = sched_getaffinity(0, cpusize, &cpuset);
    if (ret == -1) {
        fprintf(stdout, "sched_getaffinity %lu %ld\n", tid, *cpuid);
        return;
    }

    for (size_t i = 0; i < num_processors; i++) {
        if (CPU_ISSET(i, &cpuset)) {
            fprintf(stdout, "Current process %lu is bound to CPU core %zu.\n", tid, i);
            break;
        }
    }
    sleep((*cpuid) + 5);
    while (1) { }
    return;
}

void start_thread(long cpuid)
{
    worker_t *worker = NULL;
    context[cpuid] = cpuid;
    worker = worker_create(&context[cpuid], thread_func);
    if (worker == NULL) {
        fprintf(stdout, "create worker error\n");
    }
    return;
}

int daemon_forever(void)
{
    num_processors = sysconf(_SC_NPROCESSORS_ONLN);
    if (num_processors == -1) {
        perror("sysconf");
        return 1;
    }
    fprintf(stdout, "Total number of CPUs: %ld\n", num_processors);
    for (long i=0; i < num_processors; i++) {
      start_thread(i);
    }

    while(1) {
      sleep(3);
    }
}
